package com.autumn.sms.service.services.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.autumn.application.dto.PageQueryResult;
import com.autumn.application.dto.input.DefaultPrimaryKeyInput;
import com.autumn.application.dto.input.PageQueryInput;
import com.autumn.application.dto.input.QueryCriteriaItemInput;
import com.autumn.mybatis.criterion.Criteria;
import com.autumn.mybatis.criterion.IQuerySection;
import com.autumn.mybatis.criterion.ISpecifyUpdateSection;
import com.autumn.mybatis.criterion.Query;
import com.autumn.mybatis.criterion.SpecifyUpdate;
import com.autumn.sms.VerificationCodeType;
import com.autumn.sms.service.consts.ServiceConsts;
import com.autumn.sms.service.entities.SmsAppTemplate;
import com.autumn.sms.service.entities.StandardTemplate;
import com.autumn.sms.service.entities.StandardTemplateParameter;
import com.autumn.sms.service.repositories.ISmsAppTemplatePlatformRepository;
import com.autumn.sms.service.repositories.ISmsAppTemplateRepository;
import com.autumn.sms.service.repositories.IStandardTemplateParameterRepository;
import com.autumn.sms.service.repositories.IStandardTemplateRepository;
import com.autumn.sms.service.services.ICacheService;
import com.autumn.sms.service.services.IStandardTemplateService;
import com.autumn.sms.service.services.dto.input.StandardTemplateInput;
import com.autumn.sms.service.services.dto.input.StandardTemplateUpdateInput;
import com.autumn.sms.service.services.dto.output.StandardTemplateOutput;
import com.autumn.sms.service.services.dto.output.StandardTemplateParameterOutput;
import com.autumn.sms.service.utils.AuditUtils;
import com.autumn.util.AutoMapUtils;
import com.autumn.util.DataRollbackException;
import com.autumn.validation.ValidationException;

/**
 * 标准模板服务
 * 
 * @author JuWa ▪ Zhang
 * @date 2018年1月13日
 * @since jdk 1.8
 */
@Service
public class StandardTemplateServiceImpl extends AbstractBasicService<IStandardTemplateRepository, StandardTemplate>
		implements IStandardTemplateService {

	@Autowired
	private ICacheService cacheService;

	@Autowired
	private ISmsAppTemplateRepository appTemplateRepo;

	@Autowired
	private ISmsAppTemplatePlatformRepository appTemplatePlatformRepo;

	@Autowired
	private IStandardTemplateRepository standardTemplateRepo;

	@Autowired
	private IStandardTemplateParameterRepository standardTemplateParamRepo;

	@Override
	public StandardTemplateOutput add(StandardTemplateInput input) {
		checkIsDuplicateTemplate(input.getCode());
		StandardTemplate template = AutoMapUtils.mapTo(StandardTemplate.class, input);
		template.insertAuditingInitialize();
		// 新增标准模板设置为草稿状态
		template.setStatus(ServiceConsts.Status.STATUS_DRAFT);
		//若是验证码，检查是否是设置的验证码类型
		if (input.getIsVerificationCode()) {
			if(VerificationCodeType.getName(input.getVerificationCodeType()) == null) {
				throw new ValidationException("暂不支持的验证码类型：" + input.getVerificationCodeType());
			}
		}
		standardTemplateRepo.insert(template);
		StandardTemplateOutput mapTo = AutoMapUtils.mapTo(StandardTemplateOutput.class, template);
		// 新增该标准模板下的标准模板参数集合
		List<StandardTemplateParameterOutput> parameterOutputs = batchInsertStandardTemplateParam(template);
		mapTo.setParameters(parameterOutputs);
		return mapTo;
	}

	/**
	 * 批量添加标准模板参数集合
	 * 
	 * @param template
	 *              需要添加模板参数的标准模板
	 * @return 标准模板参数输出对象集合
	 */
	private List<StandardTemplateParameterOutput> batchInsertStandardTemplateParam(StandardTemplate template) {
		List<StandardTemplateParameter> parameters = template.getParameters();
		List<StandardTemplateParameterOutput> parameterOutputs = new ArrayList<>();
		if (parameters != null && parameters.size() > 0) {
			for (int i = 0; i < parameters.size(); i++) {
				StandardTemplateParameter item = parameters.get(i);
				item.setAutoSortId(i + 1);
				item.setTemplateId(template.getId());
			}
			standardTemplateParamRepo.batchInsert(parameters);
			parameterOutputs = AutoMapUtils.mapList(parameters, StandardTemplateParameterOutput.class);
		}
		return parameterOutputs;
	}

	/**
	 * 检测是否会重复同样的标准模板code
	 * 
	 * @param code
	 *              标准模板code
	 */
	private void checkIsDuplicateTemplate(String code) {
		Query query = new Query(StandardTemplate.class);
		AuditUtils.filterDelete(query);
		query.eq("code", code);
		StandardTemplate template = standardTemplateRepo.selectFirst(query.builderSection());
		if (template != null) {
			throw new ValidationException(String.format("标准模板code为 [%s]  的记录已存在", code));
		}
	}

	@Override
	@Transactional(rollbackFor = DataRollbackException.class)
	public StandardTemplateOutput modify(StandardTemplateInput input) {
		StandardTemplateUpdateInput updateInput = (StandardTemplateUpdateInput) input;
		StandardTemplate standardTemplate = checkIsExistEntityByPrimaryId(updateInput.getId());
		if (standardTemplate.getStatus() == ServiceConsts.Status.STATUS_RELEASE) {
			throw new ValidationException("发布状态的标准模板不能修改");
		}
		if (!updateInput.getCode().equalsIgnoreCase(standardTemplate.getCode())) {
			checkIsDuplicateTemplate(input.getCode());
		}
		AutoMapUtils.map(updateInput, standardTemplate);
		standardTemplate.updateAuditing();
		standardTemplateRepo.update(standardTemplate);
		// 删除该标准模板下的标准模板参数集合，重新添加
		Criteria criteria = new Criteria(StandardTemplateParameter.class);
		criteria.eq("templateId", standardTemplate.getId());
		standardTemplateParamRepo.deleteByWhere(criteria.builderSection());
		// 重新添加
		List<StandardTemplateParameterOutput> parameterOutputs = batchInsertStandardTemplateParam(standardTemplate);
		StandardTemplateOutput standardTemplateOutput = AutoMapUtils.mapTo(StandardTemplateOutput.class,
				standardTemplate);
		standardTemplateOutput.setParameters(parameterOutputs);
		return standardTemplateOutput;
	}

	@Override
	@Transactional(rollbackFor = DataRollbackException.class)
	public void delete(DefaultPrimaryKeyInput input) {
		StandardTemplate standardTemplate = checkIsExistEntityByPrimaryId(input.getId());
		if (standardTemplate.getStatus() == ServiceConsts.Status.STATUS_RELEASE) {
			throw new ValidationException("发布状态的标准模板不能删除");
		}
		ISpecifyUpdateSection section = AuditUtils.softDeleteById(StandardTemplate.class, input.getId());
		standardTemplateRepo.updateBySpecify(section);
		// 删除该标准模板下的标准模板参数集合
		Criteria criteria = new Criteria(StandardTemplateParameter.class);
		criteria.eq("templateId", input.getId());
		standardTemplateParamRepo.deleteByWhere(criteria.builderSection());
		// 删除该标准模板支持的对应应用模板
		SpecifyUpdate update = new SpecifyUpdate(SmsAppTemplate.class);
		update.set("isDelete", true).set("gmtDelete", new Date()).eq("templateId", input.getId());
		appTemplateRepo.updateBySpecify(update.builderSection());
		// 删除该标准模板对应应用模板下的所有的应用-模板-平台
		appTemplatePlatformRepo.deleteByTemplateId(input.getId());
	}

	@Override
	public StandardTemplateOutput get(DefaultPrimaryKeyInput input) {
		StandardTemplate standardTemplate = checkIsExistEntityByPrimaryId(input.getId());
		// 获取该标准模板下的标准模板参数
		Query query = new Query(StandardTemplateParameter.class);
		query.eq("templateId", input.getId());
		List<StandardTemplateParameter> parameters = standardTemplateParamRepo.selectList(query.builderSection());
		List<StandardTemplateParameterOutput> mapList = AutoMapUtils.mapList(parameters,
				StandardTemplateParameterOutput.class);
		StandardTemplateOutput out = AutoMapUtils.mapTo(StandardTemplateOutput.class, standardTemplate);
		out.setParameters(mapList);
		return out;
	}

	@Override
	protected IStandardTemplateRepository getRepository() {
		return standardTemplateRepo;
	}

	@Override
	protected Class<StandardTemplate> getEntityClass() {
		return StandardTemplate.class;
	}

	@Override
	public void release(DefaultPrimaryKeyInput input) {
		StandardTemplate standardTemplate = checkIsExistEntityByPrimaryId(input.getId());
		if (standardTemplate.getStatus() == ServiceConsts.Status.STATUS_RELEASE) {
			throw new ValidationException(String.format("标准模板表中主键ID为 [%s] 的记录已发布", input.getId()));
		}
		standardTemplate.updateAuditing();
		standardTemplate.setStatus(ServiceConsts.Status.STATUS_RELEASE);
		standardTemplateRepo.update(standardTemplate);
	}

	@Override
	@Transactional(rollbackFor = DataRollbackException.class)
	public void disable(DefaultPrimaryKeyInput input) {
		StandardTemplate standardTemplate = checkIsExistEntityByPrimaryId(input.getId());
		if (standardTemplate.getStatus() == ServiceConsts.Status.STATUS_DISABLE) {
			throw new ValidationException(String.format("标准模板表中主键ID为 [%s] 的记录已停用", input.getId()));
		}
		standardTemplate.updateAuditing();
		standardTemplate.setStatus(ServiceConsts.Status.STATUS_DISABLE);
		standardTemplateRepo.update(standardTemplate);

		// 停用该标准模板支持的对应应用模板
		SpecifyUpdate update = new SpecifyUpdate(SmsAppTemplate.class);
		update.set("status", ServiceConsts.Status.STATUS_DISABLE).set("gmtModified", new Date())
				.eq("templateId", input.getId()).eq("isDelete", false);
		appTemplateRepo.updateBySpecify(update.builderSection());
		// 刷新redis缓存
		cacheService.removeAllSendTemplate();
	}

	@Override
	public PageQueryResult<StandardTemplateOutput> pageQuery(PageQueryInput input) {
		Query query = new Query(StandardTemplate.class);
		List<QueryCriteriaItemInput> criterias = input.getCriterias();
		if (criterias != null && criterias.size() > 0) {
			query.criteria(criterias);
		}
		Integer maxValue = getPageMaxValue();
		if (input.getPageSize() > maxValue) {
			input.setPageSize(maxValue);
		}
		 query.eq("isDelete", false);
		IQuerySection section = query.builderSection();
		int count = standardTemplateRepo.countByWhere(section);
		PageQueryResult<StandardTemplateOutput> result = new PageQueryResult<StandardTemplateOutput>(
				input.getCurrentPage(), input.getPageSize(), count);
		if (count > 0) {
			query.page(result.getCurrentPage(), result.getPageSize());
			List<StandardTemplate> selectList = standardTemplateRepo.selectList(query.builderSection());
			result.setItems(AutoMapUtils.mapList(selectList, StandardTemplateOutput.class));
		}
		return result;
	}

}
